<?php
/**
 * 版权所有 2016-2022 lizhongwen，并保留所有权利;
 * 说明: 这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和使用；不允许对程序代码以任何形式任何目的的再发布;
 * 作者: lizhongwen;
 * 作者主页: http://www.lizhongwen.com;
 * 邮箱: lizhongwen@lizhongwen.common;
 * QQ: 360811363;
 */

namespace application\filter;

use application\core\Filter;
use application\core\Lib;
use application\core\RedisUtil;
use application\core\Request;
use modules\sys\mapper\AccountMapper;
use modules\sys\mapper\AccountTokenMapper;
use modules\sys\mapper\ActionMapper;
use modules\sys\mapper\PageMapper;
use modules\sys\mapper\RolePageActionMapper;

class SysFilter
{
    public static $uid;
    public static $token;
    public static $accountName;
    public static $roleIds;

    //从redis或者数据库获取token信息
    protected function getTokenRs()
    {
        if (REDIS_ENABLE) {
            //如果启用了redis，则从redis查询用户信息
            $hGet = RedisUtil::instance()->hGet("sys_account_token", self::$uid);
            $tokenRs = json_decode($hGet, true);
        } else {
            $tokenRs = AccountTokenMapper::queryByToken(['token' => self::$token]);
        }
        return $tokenRs;
    }

    //token续期
    protected function renewToken($tokenRs)
    {
        if (REDIS_ENABLE) {
            //更新redis过期时间
            $tokenRs['expire_time'] = time() + TOKEN_EXPIRE_TIME;
            RedisUtil::instance()->hSet("sys_account_token", self::$uid, json_encode($tokenRs, JSON_UNESCAPED_UNICODE));
        } else {
            //更新数据库过期时间
            AccountTokenMapper::editTokenExpireTime(['expire_time' => time() + TOKEN_EXPIRE_TIME, 'account_id' => self::$uid]);
        }
    }

    //删除token
    protected function removeToken()
    {
        if (REDIS_ENABLE) {
            RedisUtil::instance()->hDel("sys_account_token", self::$uid);
        } else {
            //更新数据库过期时间
            AccountTokenMapper::delByAccountId(['account_id' => self::$uid]);
        }
    }

    public function filter($controllerName, $actionName, $pars)
    {
        //判断页面是否校验token
        $lupCheckToken = Lib::getFunctionAnnotation(Filter::$controllerPath, $actionName, "@lupCheckToken");
        if ($lupCheckToken == "false") {
            return;
        }
        if (empty(self::$token) || empty(self::$uid)) {
//            http_response_code(401);
            Lib::outputJson(['code' => 401, 'msg' => '您还未登录，请登录.']);
        }
        $tokenRs = $this->getTokenRs();

        //校验token是否失效
        if (empty($tokenRs)) {
            $this->removeToken();
//            http_response_code(401);
            Lib::outputJson(['code' => 401, 'msg' => '登录信息失效，请重新登录!']);
        }
        if ($tokenRs['token'] != self::$token) {
//            http_response_code(401);
            Lib::outputJson(['code' => 401, 'msg' => '登录信息失效，请重新登录!']);
        }
        $expireTime = $tokenRs['expire_time'];
        if ($expireTime < time()) {
            $this->removeToken();
//            http_response_code(401);
            Lib::outputJson(['code' => 401, 'msg' => '登录信息失效，请重新登录!']);
        }
        $tokenIp = $tokenRs['ip'];
        if (Lib::realIp() != $tokenIp) {
            $this->removeToken();
//            http_response_code(401);
            Lib::outputJson(['code' => 401, 'msg' => '登录信息失效，请重新登录!']);
        }
        //一个小时续期一次token
        if (($expireTime - time()) <= (TOKEN_EXPIRE_TIME - NEED_CREATE_SECOND)) {
            $this->renewToken($tokenRs);
        }
        //查询用户信息
        $accountRs = AccountMapper::query(['id' => self::$uid]);
        if (empty($accountRs)) {
            $this->removeToken();
//            http_response_code(401);
            Lib::outputJson(['code' => 401, 'msg' => '登录信息失效，请重新登录!']);
        }
        self::$accountName = $accountRs['account_name'];
        $roleIds = $accountRs['role_ids'];
        if (empty($roleIds)) {
            $roleIds = "0";
        }
        self::$roleIds = $roleIds;
        $pageRs = PageMapper::lists();
        $pageRs = array_column($pageRs, NULL, "id");
        $actionRs = ActionMapper::lists();
        $actionRs = array_column($actionRs, NULL, "id");
        $lupCode = Lib::getFunctionAnnotation(Filter::$controllerPath, $actionName, "@lupRoleCode");

        $pageActionRs = RolePageActionMapper::listsByRoleIdsIn(['role_ids' => $roleIds]);
        $allCodeArr = [];
        foreach ($pageActionRs as $v) {
            $pageId = $v['page_id'];
            $actionIds = $v['action_ids'];
            $actionIdsArr = explode(",", $actionIds);
            foreach ($actionIdsArr as $aid) {
                if ($aid == 'auth') {
                    if ($pageRs[$pageId]['code']) {
                        $allCodeArr[] = $pageRs[$pageId]['code'];
                    }
                } else {
                    if ($actionRs[$aid]['code']) {
                        $allCodeArr[] = $actionRs[$aid]['code'];
                    }
                }
            }
        }
        //获取controller 的code 的交集
        if (!empty($lupCode) && !array_intersect(explode("|", $lupCode), $allCodeArr)) {
//            http_response_code(403);
            Lib::outputJson(['code' => 403, 'msg' => '暂无权限']);
        }
        unset($controllerName);
        unset($pars);
    }

    public function run($controllerName, $actionName, $param)
    {
        self::$uid = Request::getHeader("accessuid");
        self::$token = Request::getHeader("accesstoken");
        if(empty(self::$uid)&&!empty(Request::request('accessuid'))){
            self::$uid = Request::request("accessuid");
        }
        if(empty(self::$token)&&!empty(Request::request('accesstoken'))){
            self::$token = Request::request("accesstoken");
        }
        $this->filter($controllerName, $actionName, $param);
    }
}

